package com.task.core.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import com.task.common.constant.ErrorCodeConstants;
import com.task.common.enums.ImportStatusEnum;
import com.task.common.utils.TableNameUtils;
import com.task.core.domain.DataPreAvailableInfo;
import com.task.core.domain.MissionInfo;
import com.task.core.domain.info.*;
import com.task.core.dto.request.DataSourceDTO;
import com.task.core.dto.response.DataContentInfoResposeDTO;
import com.task.core.service.*;
import com.task.core.vo.resp.DatasourceDetailRespVo;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson2.JSONObject;
import com.task.common.annotation.DataScope;
import com.task.common.domain.info.KeyAndValue;
import com.task.common.enums.DuplicateConditionEnum;
import com.task.common.exception.ServiceException;
import com.task.common.utils.SecurityUtils;
import com.task.common.utils.StringUtils;
import com.task.common.utils.SystemFunctionUtil;
import com.task.common.utils.uuid.UUID;
import com.task.core.domain.DatasourceInfo;
import com.task.core.dto.request.DatasourceOptionRequestDTO;
import com.task.core.dto.request.DatasourceRequestDTO;
import com.task.core.mapper.DataOperationMapper;
import com.task.core.mapper.DatasourceMapper;

import org.springframework.util.ObjectUtils;
import software.amazon.awssdk.services.s3.endpoints.internal.Value.Int;

/**
 * @author 迪迦.
 * @date 2024/11/4 17:24
 */
@Service("DatasourceService")
public class DatasourceServiceImpl implements DatasourceService {

  @Resource
  private DatasourceMapper datasourceMapper;

  @Resource
  private SendHistoryService sendHistoryService;

  @Resource
  private MissionService missionService;

  @Resource
  private DataOperationMapper dataOperationMapper;

  @Resource
  private DataPreAvailableService dataPreAvailableService;

  @Resource
  private DataNoticeService dataNoticeService;


  @Override
  @DataScope(deptAlias = "dept", userAlias = "su")
  public List<DatasourceInfo> getDatasourceByPage(DatasourceRequestDTO request) {
    //request.setOperationBy(SecurityUtils.checkAdmin());
    return datasourceMapper.getDatasourceByPage(request);
  }

  @Override
  @DataScope(deptAlias = "dept", userAlias = "su")
  public List<KeyAndValue> getDatasourceForOption(DatasourceRequestDTO request) {
    //request.setOperationBy(SecurityUtils.checkAdmin());
    return datasourceMapper.getDatasourceForOption(request);
  }

  @Override
  public void addDatasource(DatasourceRequestDTO request) {
    request.setOperationBy(SecurityUtils.getLoginUser().getUserId());
    request.setCode(UUID.randomUUID().toString().replace("-", ""));
    datasourceMapper.addDatasource(request);
  }

  @Override
  public void modifyDatasource(DatasourceRequestDTO request) {
    request.setOperationBy(SecurityUtils.getLoginUser().getUserId());
    Integer integer = datasourceMapper.modifyDatasource(request);
    if(integer == 0) {
      throw new ServiceException("code不存在");
    }
  }

  @Override
  public void deleteDatasource(String datasourceCode, Long userId) {
    Integer integer = datasourceMapper.deleteDatasource(datasourceCode, userId);
    if(integer == 0) {
      throw new ServiceException("code不存在");
    }
    //删除关联数据
    for (int i=1 ;i<=20;i++){
     String tableName = SystemFunctionUtil.TABLE_PREFIX_INFO+i ;
      dataOperationMapper.deleteDataBySourceCode(datasourceCode,tableName);
    }
    dataPreAvailableService.deletePreAvailableData(datasourceCode);

    //删除任务关联的数据
    datasourceMapper.deleteMissionDatasourceRelation(datasourceCode);
    //删除数据使用记录表
    datasourceMapper.deleteRelationMissionSourceUseDataCount(datasourceCode);
  }

  @Override
  public DatasourceInfo getDataSourceByCode(String dataSourceCode) {
    return datasourceMapper.getDatasourceByCode(dataSourceCode);
  }

  @Override
  public List<DatasourceInfo> getDataSourceByCodes(List<String> codes) {
    return datasourceMapper.getDataSourceByCodes(codes);
  }

  @Override
  public void updateDataCount(Integer intValue, String dataSourceCode) {
    datasourceMapper.updateDataCount(intValue, dataSourceCode);
  }

  @Override
  public void updateDataCountDecrement(String datasourceCode, Integer deleteCount) {
    datasourceMapper.updateDataCountDecrement(datasourceCode, deleteCount);
  }

  @Override
  public void deleteDatasourceByMissionCode(String missionCode) {
    datasourceMapper.deleteDatasourceByMissionCode(missionCode);
  }

  @Override
  public void addSourceByMissionCode(List<RelationMissionSourceInfo> sourceInfos) {
    datasourceMapper.addSourceByMissionCode(sourceInfos);
  }

  @Override
  @DataScope(deptAlias = "dept", userAlias = "su")
  public List<DatasourceInfoOptionInfo> getDatasourceForOptionByMission(DatasourceOptionRequestDTO request) {

    List<DatasourceInfoOptionInfo> result = new ArrayList<>();

    MissionInfo missionByCode = missionService.getMissionByCode(request.getMissionCode(), false);

    List<DatasourceInfo> infos = datasourceMapper.getDatasourceForOptionByMission(request);

    if(!CollectionUtils.isEmpty(infos)){
      List<String> indexTableNames =new ArrayList<>();
      for (int i = 1; i <= 20 ; i++) {
        String tableName = SystemFunctionUtil.RELATION_MISSION_DATA_PREFIX+i;
        indexTableNames.add(tableName);
      }
      if (CollectionUtils.isEmpty(indexTableNames)) {
        throw new ServiceException("没有数据发送记录表,联系管理员初始化数据库");
      }

      for (DatasourceInfo info : infos) {

        Integer useCount = 0;
        if(!ObjectUtils.isEmpty(request.getMissionCode()) && !ObjectUtils.isEmpty(missionByCode)){
          useCount = dataOperationMapper.getUseDataCountByFilterAndSourceCode(
                  missionByCode.getCode(),
                  missionByCode.getAffiliateCode(),
                  missionByCode.getAdvertiserCode(),
                  info.getCode(),
                  indexTableNames,
                  info.getFailureThreshold());
        }
        result.add(new DatasourceInfoOptionInfo(info.getDatasourceName(), info.getCode(), info.getDataCount(), useCount));
      }
      return result;
    }else {
      return result;
    }
  }

  @Override
  @DataScope(deptAlias = "dept", userAlias = "su")
  @PreAuthorize("@ss.hasPermi('dataSource:list')")
  public List<DatasourceInfo> getAllDataSource(DatasourceOptionRequestDTO request) {
    return datasourceMapper.getAllDataSource(request);
  }

  @Override
  @Transactional
  public void clearDatasource(String datasourceCode) {
    Long userId = SecurityUtils.getUserId();
    DatasourceInfo datasourceByCode = datasourceMapper.getDatasourceByCode(datasourceCode);
    if(ObjectUtils.isEmpty(datasourceByCode)){
      throw new ServiceException(ErrorCodeConstants.DATA_SOURCE_NOT_EXIST.getMsg());
    }
    new Thread(() -> {
      try {
        for (int i=1 ;i<=20;i++){
          String tableName = SystemFunctionUtil.TABLE_PREFIX_INFO+i ;
          dataOperationMapper.deleteDataBySourceCode(datasourceCode,tableName);
        }
        datasourceMapper.updateDataSourceCount(datasourceCode,userId);
        dataPreAvailableService.updateUseBySourceCode(datasourceCode);
        missionService.updateMissionUseDataCountRelation(datasourceCode);
        dataNoticeService.sendMessage(datasourceCode,datasourceByCode.getDatasourceName()+","+ErrorCodeConstants.DATA_CLEAR_SUCCESS.getMsg());
      } catch (Exception e) {
        e.printStackTrace();
        throw new ServiceException(ErrorCodeConstants.DATA_CLEARING_FAILED.getMsg());
      }
    }).start();
  }

  @Override
  public DataContentInfoResposeDTO showDatasource(String datasourceCode) {
    List<String> tableName = TableNameUtils.getDataContentTableNameByPrefix(TableNameUtils.TABLE_DATA_CONTENT_INFO);
    DataContentInfo dataContentInfo = dataOperationMapper.showDatasource(datasourceCode, tableName);
    if(ObjectUtils.isEmpty(dataContentInfo)){
      return new DataContentInfoResposeDTO();
    }
    return new DataContentInfoResposeDTO(dataContentInfo.getDataContent());
  }

  @Override
  @DataScope(deptAlias = "dept",userAlias = "su")
  public DatasourceDetailRespVo getDataSoucreDetail(String dataSourceCode) {
    DatasourceRequestDTO datasourceRequestDTO = new DatasourceRequestDTO();
    datasourceRequestDTO.setCode(dataSourceCode);
    return datasourceMapper.getDataSoucreDetail(datasourceRequestDTO);
  }

  @Override
  @DataScope(deptAlias = "dept", userAlias = "su")
  public List<DatasourceInfoOptionInfo> getDatasourceForOptionByMissionCode(DatasourceOptionRequestDTO request) {

    List<DatasourceInfoOptionInfo> result = new ArrayList<>();

    if(ObjectUtils.isEmpty(request.getMissionCode())){
      throw new ServiceException(ErrorCodeConstants.MISSION_CODE_NOT_EMPTY.getMsg());
    }
    MissionInfo missionByCode = missionService.getMissionByCode(request.getMissionCode(), false);

    List<DatasourceInfo> infos = datasourceMapper.getDatasourceForOptionByMission(request);

    for (DatasourceInfo info : infos) {

      Integer useCount = 0;
      if(!ObjectUtils.isEmpty(missionByCode)){
        DataPreAvailableInfo dataPreAvailableInfo = dataPreAvailableService.getUseDataCountByFilterAndSourceCode(missionByCode, info.getCode());
        if (!ObjectUtils.isEmpty(dataPreAvailableInfo) && !ObjectUtils.isEmpty(dataPreAvailableInfo.getMissionUseCount())){
          useCount = dataPreAvailableInfo.getMissionUseCount().intValue();
        }

      }
      result.add(new DatasourceInfoOptionInfo(info.getDatasourceName(), info.getCode(), info.getDataCount(), useCount));
    }
    return result;
  }

}
